# cython: language_level=3
# cython: boundscheck=False
# cython: wraparound=False
# cython: cdivision=True
# cython: nonecheck=False

import numpy as np
cimport numpy as cnp
cimport cython
from libc.stdint cimport uint8_t, uint16_t, uint32_t, int32_t
from libc.string cimport memcmp, memcpy

# 声明NumPy数组类型
ctypedef cnp.uint8_t DTYPE_t

@cython.boundscheck(False)
@cython.wraparound(False)
cdef class FastDataExtractor:
    """高性能数据提取器
    
    使用Cython优化虚拟信道、帧计数提取和payload处理
    """
    
    @staticmethod
    cdef inline uint32_t extract_vc_frame_count_1092(const uint8_t[:] payload) nogil:
        """从1092字节帧提取虚拟信道帧计数
        
        Args:
            payload: 帧数据（内存视图）
            
        Returns:
            uint32_t: 虚拟信道帧计数（3字节，大端序）
        """
        cdef uint32_t frame_count = 0
        # 1092字节帧：虚拟信道帧计数在payload的第60-62字节
        if payload.shape[0] >= 63:
            frame_count = (payload[60] << 16) | (payload[61] << 8) | payload[62]
        return frame_count
    
    @staticmethod
    cdef inline uint32_t extract_vc_frame_count_1024(const uint8_t[:] payload) nogil:
        """从1024字节帧提取虚拟信道帧计数
        
        Args:
            payload: 帧数据（内存视图）
            
        Returns:
            uint32_t: 虚拟信道帧计数（3字节，大端序）
        """
        cdef uint32_t frame_count = 0
        # 1024字节帧：虚拟信道帧计数在payload的第6-8字节
        if payload.shape[0] >= 9:
            frame_count = (payload[6] << 16) | (payload[7] << 8) | payload[8]
        return frame_count
    
    @staticmethod
    cdef inline uint8_t extract_virtual_channel_1092(const uint8_t[:] payload) nogil:
        """从1092字节帧提取虚拟信道标识
        
        Args:
            payload: 帧数据（内存视图）
            
        Returns:
            uint8_t: 虚拟信道标识（6位）
        """
        cdef uint8_t vc_id = 0
        # 1092字节帧：虚拟信道在payload的第69字节低6位
        if payload.shape[0] >= 70:
            vc_id = payload[69] & 0x3F
        return vc_id
    
    @staticmethod
    cdef inline uint8_t extract_virtual_channel_1024(const uint8_t[:] payload) nogil:
        """从1024字节帧提取虚拟信道标识
        
        Args:
            payload: 帧数据（内存视图）
            
        Returns:
            uint8_t: 虚拟信道标识（6位）
        """
        cdef uint8_t vc_id = 0
        # 1024字节帧：虚拟信道在payload的第5字节低6位
        if payload.shape[0] >= 6:
            vc_id = payload[5] & 0x3F
        return vc_id
    
    @staticmethod
    def extract_virtual_channel_frame_count_fast(cnp.ndarray[DTYPE_t, ndim=1] payload, 
                                                str frame_format):
        """Python接口：快速提取虚拟信道帧计数
        
        Args:
            payload: NumPy数组格式的帧数据
            frame_format: 帧格式（'1092', '1024', '896'）
            
        Returns:
            int: 虚拟信道帧计数
        """
        cdef const uint8_t[:] payload_view = payload
        cdef uint32_t frame_count = 0
        
        if frame_format == '1092':
            frame_count = FastDataExtractor.extract_vc_frame_count_1092(payload_view)
        elif frame_format in ('1024', '896'):
            frame_count = FastDataExtractor.extract_vc_frame_count_1024(payload_view)
            
        return int(frame_count)
    
    @staticmethod
    def extract_virtual_channel_fast(cnp.ndarray[DTYPE_t, ndim=1] payload, 
                                   str frame_format):
        """Python接口：快速提取虚拟信道标识
        
        Args:
            payload: NumPy数组格式的帧数据
            frame_format: 帧格式（'1092', '1024', '896'）
            
        Returns:
            int: 虚拟信道标识
        """
        cdef const uint8_t[:] payload_view = payload
        cdef uint8_t vc_id = 0
        
        if frame_format == '1092':
            vc_id = FastDataExtractor.extract_virtual_channel_1092(payload_view)
        elif frame_format in ('1024', '896'):
            vc_id = FastDataExtractor.extract_virtual_channel_1024(payload_view)
            
        return int(vc_id)

@cython.boundscheck(False)
@cython.wraparound(False)
def batch_extract_vc_info(list frames, str frame_format):
    """批量提取虚拟信道信息
    
    Args:
        frames: 帧列表
        frame_format: 帧格式
        
    Returns:
        tuple: (虚拟信道列表, 帧计数列表)
    """
    cdef int num_frames = len(frames)
    cdef list vc_ids = []
    cdef list frame_counts = []
    cdef cnp.ndarray[DTYPE_t, ndim=1] payload_arr
    cdef dict frame
    cdef int i
    
    for i in range(num_frames):
        frame = frames[i]
        payload = frame['payload']
        
        # 转换为NumPy数组
        if isinstance(payload, bytes):
            payload_arr = np.frombuffer(payload, dtype=np.uint8)
        else:
            payload_arr = np.asarray(payload, dtype=np.uint8)
        
        # 提取虚拟信道和帧计数
        vc_id = FastDataExtractor.extract_virtual_channel_fast(payload_arr, frame_format)
        frame_count = FastDataExtractor.extract_virtual_channel_frame_count_fast(payload_arr, frame_format)
        
        vc_ids.append(vc_id)
        frame_counts.append(frame_count)
    
    return vc_ids, frame_counts

@cython.boundscheck(False)
@cython.wraparound(False)
cdef inline void extract_comparison_data_c(const uint8_t[:] source,
                                          uint8_t[:] dest,
                                          int start_pos,
                                          int end_pos) noexcept nogil:
    """C级别的数据提取函数
    
    Args:
        source: 源数据
        dest: 目标缓冲区
        start_pos: 起始位置
        end_pos: 结束位置
    """
    cdef int i
    cdef int length = end_pos - start_pos + 1
    
    for i in range(length):
        if start_pos + i < source.shape[0]:
            dest[i] = source[start_pos + i]

@cython.boundscheck(False)
@cython.wraparound(False)
def extract_comparison_data_fast(cnp.ndarray[DTYPE_t, ndim=1] payload,
                                tuple compare_range = None,
                                str frame_format = '1092'):
    """快速提取比对数据
    
    Args:
        payload: 帧数据
        compare_range: 比对范围 (start, end)
        frame_format: 帧格式
        
    Returns:
        numpy.ndarray: 提取的数据
    """
    cdef int start_pos = 0
    cdef int end_pos = payload.shape[0] - 1
    cdef int max_len = payload.shape[0]
    
    # 根据帧格式限制最大长度
    if frame_format == '1092':
        max_len = min(max_len, 1024)
    elif frame_format == '896':
        max_len = min(max_len, 896)
    
    # 应用比对范围
    if compare_range is not None:
        start_pos = max(0, compare_range[0])
        end_pos = min(compare_range[1], max_len - 1)
    else:
        end_pos = max_len - 1
    
    # 确保范围有效
    if start_pos > end_pos:
        return np.array([], dtype=np.uint8)
    
    cdef int extract_len = end_pos - start_pos + 1
    cdef cnp.ndarray[DTYPE_t, ndim=1] result = np.empty(extract_len, dtype=np.uint8)
    cdef const uint8_t[:] source_view = payload
    cdef uint8_t[:] dest_view = result
    
    # 使用C级别的提取函数
    extract_comparison_data_c(source_view, dest_view, start_pos, end_pos)
    
    return result 